package com.wht.media.context;

import com.aizuda.zlm4j.callback.*;
import com.aizuda.zlm4j.core.ZLMApi;
import com.aizuda.zlm4j.structure.MK_EVENTS;
import com.aizuda.zlm4j.structure.MK_INI;
import com.sun.jna.Native;
import com.wht.media.config.MediaServerConfig;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Destroy;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Managed;

/**
 * 流媒体上下文
 *
 * @author lidaofu
 * @since 2023/11/28
 **/
@Slf4j
@Managed
public class MediaServerContext {

    @Inject
    private MediaServerConfig config;
    @Inject
    private IMKStreamChangeCallBack iMKStreamChangeCallBack;
    @Inject
    private IMKNoReaderCallBack iMKNoReaderCallBack;
    @Inject
    private IMKPublishCallBack iMKPublishCallBack;
    @Inject
    private IMKNoFoundCallBack imKNoFoundCallBack;
    @Inject
    private IMKFlowReportCallBack iMKFlowReportCallBack;
    @Inject
    private IMKPlayCallBack iMKPlayCallBack;
    @Inject
    private IMKRecordMp4CallBack iMKRecordMp4CallBack;
    @Inject
    private IMKRecordTsCallBack iMKRecordTsCallBack;
    @Inject
    private IMKLogCallBack iMKLogCallBack;

    public static ZLMApi ZLM_API = null;
    public static MK_EVENTS MK_EVENT = null;
    public static MK_INI MK_INI = null;

    @Init
    public void initMediaServer() {
        ZLM_API = Native.load("mk_api", ZLMApi.class);
        this.initMediaServerConf();
        this.initEvents();
        this.startMediaServer();
        log.info("【MediaServer】初始化MediaServer程序成功");
    }


    /**
     * 初始化服务器配置
     */
    public void initMediaServerConf() {
        //初始化环境配置
        MK_INI = ZLM_API.mk_ini_default();
        ZLM_API.mk_ini_set_option(MK_INI, "general.mediaServerId", "JMediaServer");
        ZLM_API.mk_ini_set_option(MK_INI, "http.notFound", "<h1 style=\"text-align:center;\">Media Server V1.0 By LiDaoFu</h1>");
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.auto_close", config.getAutoClose());
        ZLM_API.mk_ini_set_option_int(MK_INI, "general.streamNoneReaderDelayMS", config.getStreamNoneReaderDelayMs());
        ZLM_API.mk_ini_set_option_int(MK_INI, "general.maxStreamWaitMS", config.getMaxStreamWaitMs());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_ts", config.getEnableTs());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_hls", config.getEnableHls());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_fmp4", config.getEnableFmp4());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_rtsp", config.getEnableRtsp());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_rtmp", config.getEnableRtmp());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_mp4", config.getEnableMp4());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_hls_fmp4", config.getEnableHlsFmp4());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.enable_audio", config.getEnableAudio());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.mp4_as_player", config.getMp4AsPlayer());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.mp4_max_second", config.getMp4MaxSecond());
        ZLM_API.mk_ini_set_option(MK_INI, "http.rootPath", config.getRootPath());
        ZLM_API.mk_ini_set_option(MK_INI, "protocol.mp4_save_path", config.getMp4SavePath());
        ZLM_API.mk_ini_set_option(MK_INI, "protocol.hls_save_path", config.getHlsSavePath());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.hls_demand", config.getHlsDemand());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.rtsp_demand", config.getRtspDemand());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.rtmp_demand", config.getRtmpDemand());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.ts_demand", config.getTsDemand());
        ZLM_API.mk_ini_set_option_int(MK_INI, "protocol.fmp4_demand", config.getFmp4Demand());
        ZLM_API.mk_ini_set_option_int(MK_INI, "hls.broadcastRecordTs", config.getBroadcastRecordTs());
        ZLM_API.mk_ini_set_option_int(MK_INI, "hls.segNum", config.getSegNum());
        ZLM_API.mk_ini_set_option_int(MK_INI, "hls.segDur", config.getSegDur());
        ZLM_API.mk_ini_set_option(MK_INI, "rtc.externIP", config.getRtcHost());
        ZLM_API.mk_ini_set_option_int(MK_INI, "rtc.port", config.getRtcPort());
        ZLM_API.mk_ini_set_option_int(MK_INI, "rtc.tcpPort", config.getRtcPort());
        //初始化zmk服务器
        ZLM_API.mk_env_init1(config.getThreadNum(), config.getLogLevel(), config.getLogMask(), config.getLogPath(), config.getLogFileDays(), 0, null, 0, null, null);
    }

    /**
     * 初始化事件回调
     */
    public void initEvents() {
        //全局回调
        MK_EVENT = new MK_EVENTS();
        MK_EVENT.on_mk_media_changed = iMKStreamChangeCallBack;
        MK_EVENT.on_mk_media_no_reader = iMKNoReaderCallBack;
        MK_EVENT.on_mk_media_publish = iMKPublishCallBack;
        MK_EVENT.on_mk_media_not_found = imKNoFoundCallBack;
        MK_EVENT.on_mk_flow_report = iMKFlowReportCallBack;
        MK_EVENT.on_mk_media_play = iMKPlayCallBack;
 /*       MK_EVENT.on_mk_http_access = new MKHttpAccessCallBack();
        MK_EVENT.on_mk_http_request = new MKHttpRequestCallBack();
        MK_EVENT.on_mk_http_access = new MKHttpAccessCallBack();
        MK_EVENT.on_mk_http_before_access = new MKHttpBeforeAccessCallBack();*/
        MK_EVENT.on_mk_record_mp4 = iMKRecordMp4CallBack;
        MK_EVENT.on_mk_record_ts = iMKRecordTsCallBack;
        MK_EVENT.on_mk_log = iMKLogCallBack;
        //添加全局回调
        ZLM_API.mk_events_listen(MK_EVENT);
    }

    /**
     * 启动流媒体服务器
     */
    public boolean startMediaServer() {
        boolean result = false;
        //创建http服务器 0:失败,非0:端口号
        short httpServerPort = ZLM_API.mk_http_server_start(config.getHttpPort().shortValue(), 0);
        result = httpServerPort == 0;
        log.info("【MediaServer】HTTP流媒体服务启动：{}", result ? "失败" : "成功，端口：" + httpServerPort);
        //创建rtsp服务器 0:失败,非0:端口号
        short rtspServerPort = ZLM_API.mk_rtsp_server_start(config.getRtspPort().shortValue(), 0);
        result = rtspServerPort == 0;
        log.info("【MediaServer】RTSP流媒体服务启动：{}", result ? "失败" : "成功，端口：" + rtspServerPort);
        //创建rtmp服务器 0:失败,非0:端口号
        short rtmpServerPort = ZLM_API.mk_rtmp_server_start(config.getRtmpPort().shortValue(), 0);
        result = rtmpServerPort == 0;
        log.info("【MediaServer】RTMP流媒体服务启动：{}", result ? "失败" : "成功，端口：" + rtmpServerPort);
        //创建rtc服务器 0:失败,非0:端口号
        short rtcServerPort = ZLM_API.mk_rtc_server_start(config.getRtcPort().shortValue());
        result = rtcServerPort == 0;
        log.info("【MediaServer】RTC流媒体服务启动：{}", result ? "失败" : "成功，端口：" + rtcServerPort);
        return !result;
    }

    /**
     * 关闭流媒体服务器
     */
    public void stopMediaServer() {
        ZLM_API.mk_stop_all_server();
        log.info("【MediaServer】关闭所有流媒体服务");
    }

    /**
     * 释放资源
     */
    @Destroy
    public void release() {
        this.stopMediaServer();
    }


}
